home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 401-425 / disk_419 / yacc / src.lzh / Src / RCS / reader.c,v < prev    next >
Text File  |  1990-07-14  |  31KB  |  1,796 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     90.07.14.18.54.58;  author loftus;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @@
  17.  
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @#include "defs.h"
  26.  
  27. /*  The line size must be a positive integer.  One hundred was chosen    */
  28. /*  because few lines in Yacc input grammars exceed 100 characters.    */
  29. /*  Note that if a line exceeds LINESIZE characters, the line buffer    */
  30. /*  will be expanded to accomodate it.                    */
  31.  
  32. #define LINESIZE 100
  33.  
  34. char *cache;
  35. int cinc, cache_size;
  36.  
  37. int ntags, tagmax;
  38. char **tag_table;
  39.  
  40. char saw_eof, unionized;
  41. char *cptr, *line;
  42. int linesize;
  43.  
  44. bucket *goal;
  45. int prec;
  46. int gensym;
  47. char last_was_action;
  48.  
  49. int maxitems;
  50. bucket **pitem;
  51.  
  52. int maxrules;
  53. bucket **plhs;
  54.  
  55. int name_pool_size;
  56. char *name_pool;
  57.  
  58. char line_format[] = "#line %d \"%s\"\n";
  59.  
  60.  
  61. cachec(c)
  62. int c;
  63. {
  64.     assert(cinc >= 0);
  65.     if (cinc >= cache_size)
  66.     {
  67.     cache_size += 256;
  68.     cache = REALLOC(cache, cache_size);
  69.     if (cache == 0) no_space();
  70.     }
  71.     cache[cinc] = c;
  72.     ++cinc;
  73. }
  74.  
  75.  
  76. get_line()
  77. {
  78.     register FILE *f = input_file;
  79.     register int c;
  80.     register int i;
  81.  
  82.     if (saw_eof || (c = getc(f)) == EOF)
  83.     {
  84.     if (line) { FREE(line); line = 0; }
  85.     cptr = 0;
  86.     saw_eof = 1;
  87.     return;
  88.     }
  89.  
  90.     if (line == 0 || linesize != (LINESIZE + 1))
  91.     {
  92.     if (line) FREE(line);
  93.     linesize = LINESIZE + 1;
  94.     line = MALLOC(linesize);
  95.     if (line == 0) no_space();
  96.     }
  97.  
  98.     i = 0;
  99.     ++lineno;
  100.     for (;;)
  101.     {
  102.     line[i]  =  c;
  103.     if (c == '\n') { cptr = line; return; }
  104.     if (++i >= linesize)
  105.     {
  106.         linesize += LINESIZE;
  107.         line = REALLOC(line, linesize);
  108.         if (line ==  0) no_space();
  109.     }
  110.     c = getc(f);
  111.     if (c ==  EOF)
  112.     {
  113.         line[i] = '\n';
  114.         saw_eof = 1;
  115.         cptr = line;
  116.         return;
  117.     }
  118.     }
  119. }
  120.  
  121.  
  122. char *
  123. dup_line()
  124. {
  125.     register char *p, *s, *t;
  126.  
  127.     if (line == 0) return (0);
  128.     s = line;
  129.     while (*s != '\n') ++s;
  130.     p = MALLOC(s - line + 1);
  131.     if (p == 0) no_space();
  132.  
  133.     s = line;
  134.     t = p;
  135.     while ((*t++ = *s++) != '\n') continue;
  136.     return (p);
  137. }
  138.  
  139.  
  140. skip_comment()
  141. {
  142.     register char *s;
  143.  
  144.     int st_lineno = lineno;
  145.     char *st_line = dup_line();
  146.     char *st_cptr = st_line + (cptr - line);
  147.  
  148.     s = cptr + 2;
  149.     for (;;)
  150.     {
  151.     if (*s == '*' && s[1] == '/')
  152.     {
  153.         cptr = s + 2;
  154.         FREE(st_line);
  155.         return;
  156.     }
  157.     if (*s == '\n')
  158.     {
  159.         get_line();
  160.         if (line == 0)
  161.         unterminated_comment(st_lineno, st_line, st_cptr);
  162.         s = cptr;
  163.     }
  164.     else
  165.         ++s;
  166.     }
  167. }
  168.  
  169.  
  170. int
  171. nextc()
  172. {
  173.     register char *s;
  174.  
  175.     if (line == 0)
  176.     {
  177.     get_line();
  178.     if (line == 0)
  179.         return (EOF);
  180.     }
  181.  
  182.     s = cptr;
  183.     for (;;)
  184.     {
  185.     switch (*s)
  186.     {
  187.     case '\n':
  188.         get_line();
  189.         if (line == 0) return (EOF);
  190.         s = cptr;
  191.         break;
  192.  
  193.     case ' ':
  194.     case '\t':
  195.     case '\f':
  196.     case '\r':
  197.     case '\v':
  198.     case ',':
  199.     case ';':
  200.         ++s;
  201.         break;
  202.  
  203.     case '\\':
  204.         cptr = s;
  205.         return ('%');
  206.  
  207.     case '/':
  208.         if (s[1] == '*')
  209.         {
  210.         cptr = s;
  211.         skip_comment();
  212.         s = cptr;
  213.         break;
  214.         }
  215.         else if (s[1] == '/')
  216.         {
  217.         get_line();
  218.         if (line == 0) return (EOF);
  219.         s = cptr;
  220.         break;
  221.         }
  222.         /* fall through */
  223.  
  224.     default:
  225.         cptr = s;
  226.         return (*s);
  227.     }
  228.     }
  229. }
  230.  
  231.  
  232. int
  233. keyword()
  234. {
  235.     register int c;
  236.     char *t_cptr = cptr;
  237.  
  238.     c = *++cptr;
  239.     if (isalpha(c))
  240.     {
  241.     cinc = 0;
  242.     for (;;)
  243.     {
  244.         if (isalpha(c))
  245.         {
  246.         if (isupper(c)) c = tolower(c);
  247.         cachec(c);
  248.         }
  249.         else if (isdigit(c) || c == '_' || c == '.' || c == '$')
  250.         cachec(c);
  251.         else
  252.         break;
  253.         c = *++cptr;
  254.     }
  255.     cachec(NUL);
  256.  
  257.     if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
  258.         return (TOKEN);
  259.     if (strcmp(cache, "type") == 0)
  260.         return (TYPE);
  261.     if (strcmp(cache, "left") == 0)
  262.         return (LEFT);
  263.     if (strcmp(cache, "right") == 0)
  264.         return (RIGHT);
  265.     if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
  266.         return (NONASSOC);
  267.     if (strcmp(cache, "start") == 0)
  268.         return (START);
  269.     if (strcmp(cache, "union") == 0)
  270.         return (UNION);
  271.     if (strcmp(cache, "ident") == 0)
  272.         return (IDENT);
  273.     }
  274.     else
  275.     {
  276.     ++cptr;
  277.     if (c == '{')
  278.         return (TEXT);
  279.     if (c == '%' || c == '\\')
  280.         return (MARK);
  281.     if (c == '<')
  282.         return (LEFT);
  283.     if (c == '>')
  284.         return (RIGHT);
  285.     if (c == '0')
  286.         return (TOKEN);
  287.     if (c == '2')
  288.         return (NONASSOC);
  289.     }
  290.     syntax_error(lineno, line, t_cptr);
  291.     /*NOTREACHED*/
  292. }
  293.  
  294.  
  295. copy_ident()
  296. {
  297.     register int c;
  298.     register FILE *f = output_file;
  299.  
  300.     c = nextc();
  301.     if (c == EOF) unexpected_EOF();
  302.     if (c != '"') syntax_error(lineno, line, cptr);
  303.     ++outline;
  304.     fprintf(f, "#ident \"");
  305.     for (;;)
  306.     {
  307.     c = *++cptr;
  308.     if (c == '\n')
  309.     {
  310.         fprintf(f, "\"\n");
  311.         return;
  312.     }
  313.     putc(c, f);
  314.     if (c == '"')
  315.     {
  316.         putc('\n', f);
  317.         ++cptr;
  318.         return;
  319.     }
  320.     }
  321. }
  322.  
  323.  
  324. copy_text()
  325. {
  326.     register int c;
  327.     int quote;
  328.     register FILE *f = text_file;
  329.     int need_newline = 0;
  330.     int t_lineno = lineno;
  331.     char *t_line = dup_line();
  332.     char *t_cptr = t_line + (cptr - line - 2);
  333.  
  334.     if (*cptr == '\n')
  335.     {
  336.     get_line();
  337.     if (line == 0)
  338.         unterminated_text(t_lineno, t_line, t_cptr);
  339.     }
  340.     if (!lflag) fprintf(f, line_format, lineno, input_file_name);
  341.  
  342. loop:
  343.     c = *cptr++;
  344.     switch (c)
  345.     {
  346.     case '\n':
  347.     next_line:
  348.     putc('\n', f);
  349.     need_newline = 0;
  350.     get_line();
  351.     if (line) goto loop;
  352.     unterminated_text(t_lineno, t_line, t_cptr);
  353.  
  354.     case '\'':
  355.     case '"':
  356.     {
  357.         int s_lineno = lineno;
  358.         char *s_line = dup_line();
  359.         char *s_cptr = s_line + (cptr - line - 1);
  360.  
  361.         quote = c;
  362.         putc(c, f);
  363.         for (;;)
  364.         {
  365.         c = *cptr++;
  366.         putc(c, f);
  367.         if (c == quote)
  368.         {
  369.             need_newline = 1;
  370.             FREE(s_line);
  371.             goto loop;
  372.         }
  373.         if (c == '\n')
  374.             unterminated_string(s_lineno, s_line, s_cptr);
  375.         if (c == '\\')
  376.         {
  377.             c = *cptr++;
  378.             putc(c, f);
  379.             if (c == '\n')
  380.             {
  381.             get_line();
  382.             if (line == 0)
  383.                 unterminated_string(s_lineno, s_line, s_cptr);
  384.             }
  385.         }
  386.         }
  387.     }
  388.  
  389.     case '/':
  390.     putc(c, f);
  391.     need_newline = 1;
  392.     c = *cptr;
  393.     if (c == '/')
  394.     {
  395.         putc('*', f);
  396.         while ((c = *++cptr) != '\n')
  397.         {
  398.         if (c == '*' && cptr[1] == '/')
  399.             fprintf(f, "* ");
  400.         else
  401.             putc(c, f);
  402.         }
  403.         fprintf(f, "*/");
  404.         goto next_line;
  405.     }
  406.     if (c == '*')
  407.     {
  408.         int c_lineno = lineno;
  409.         char *c_line = dup_line();
  410.         char *c_cptr = c_line + (cptr - line - 1);
  411.  
  412.         putc('*', f);
  413.         ++cptr;
  414.         for (;;)
  415.         {
  416.         c = *cptr++;
  417.         putc(c, f);
  418.         if (c == '*' && *cptr == '/')
  419.         {
  420.             putc('/', f);
  421.             ++cptr;
  422.             FREE(c_line);
  423.             goto loop;
  424.         }
  425.         if (c == '\n')
  426.         {
  427.             get_line();
  428.             if (line == 0)
  429.             unterminated_comment(c_lineno, c_line, c_cptr);
  430.         }
  431.         }
  432.     }
  433.     need_newline = 1;
  434.     goto loop;
  435.  
  436.     case '%':
  437.     case '\\':
  438.     if (*cptr == '}')
  439.     {
  440.         if (need_newline) putc('\n', f);
  441.         ++cptr;
  442.         FREE(t_line);
  443.         return;
  444.     }
  445.     /* fall through */
  446.  
  447.     default:
  448.     putc(c, f);
  449.     need_newline = 1;
  450.     goto loop;
  451.     }
  452. }
  453.  
  454.  
  455. copy_union()
  456. {
  457.     register int c;
  458.     int quote;
  459.     int depth;
  460.     int u_lineno = lineno;
  461.     char *u_line = dup_line();
  462.     char *u_cptr = u_line + (cptr - line - 6);
  463.  
  464.     if (unionized) over_unionized(cptr - 6);
  465.     unionized = 1;
  466.  
  467.     if (!lflag)
  468.     fprintf(text_file, line_format, lineno, input_file_name);
  469.  
  470.     fprintf(text_file, "typedef union");
  471.     if (dflag) fprintf(union_file, "typedef union");
  472.  
  473.     depth = 0;
  474. loop:
  475.     c = *cptr++;
  476.     putc(c, text_file);
  477.     if (dflag) putc(c, union_file);
  478.     switch (c)
  479.     {
  480.     case '\n':
  481.     next_line:
  482.     get_line();
  483.     if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
  484.     goto loop;
  485.  
  486.     case '{':
  487.     ++depth;
  488.     goto loop;
  489.  
  490.     case '}':
  491.     if (--depth == 0)
  492.     {
  493.         fprintf(text_file, " YYSTYPE;\n");
  494.         FREE(u_line);
  495.         return;
  496.     }
  497.     goto loop;
  498.  
  499.     case '\'':
  500.     case '"':
  501.     {
  502.         int s_lineno = lineno;
  503.         char *s_line = dup_line();
  504.         char *s_cptr = s_line + (cptr - line - 1);
  505.  
  506.         quote = c;
  507.         for (;;)
  508.         {
  509.         c = *cptr++;
  510.         putc(c, text_file);
  511.         if (dflag) putc(c, union_file);
  512.         if (c == quote)
  513.         {
  514.             FREE(s_line);
  515.             goto loop;
  516.         }
  517.         if (c == '\n')
  518.             unterminated_string(s_lineno, s_line, s_cptr);
  519.         if (c == '\\')
  520.         {
  521.             c = *cptr++;
  522.             putc(c, text_file);
  523.             if (dflag) putc(c, union_file);
  524.             if (c == '\n')
  525.             {
  526.             get_line();
  527.             if (line == 0)
  528.                 unterminated_string(s_lineno, s_line, s_cptr);
  529.             }
  530.         }
  531.         }
  532.     }
  533.  
  534.     case '/':
  535.     c = *cptr;
  536.     if (c == '/')
  537.     {
  538.         putc('*', text_file);
  539.         if (dflag) putc('*', union_file);
  540.         while ((c = *++cptr) != '\n')
  541.         {
  542.         if (c == '*' && cptr[1] == '/')
  543.         {
  544.             fprintf(text_file, "* ");
  545.             if (dflag) fprintf(union_file, "* ");
  546.         }
  547.         else
  548.         {
  549.             putc(c, text_file);
  550.             if (dflag) putc(c, union_file);
  551.         }
  552.         }
  553.         fprintf(text_file, "*/\n");
  554.         if (dflag) fprintf(union_file, "*/\n");
  555.         goto next_line;
  556.     }
  557.     if (c == '*')
  558.     {
  559.         int c_lineno = lineno;
  560.         char *c_line = dup_line();
  561.         char *c_cptr = c_line + (cptr - line - 1);
  562.  
  563.         putc('*', text_file);
  564.         if (dflag) putc('*', union_file);
  565.         ++cptr;
  566.         for (;;)
  567.         {
  568.         c = *cptr++;
  569.         putc(c, text_file);
  570.         if (dflag) putc(c, union_file);
  571.         if (c == '*' && *cptr == '/')
  572.         {
  573.             putc('/', text_file);
  574.             if (dflag) putc('/', union_file);
  575.             ++cptr;
  576.             FREE(c_line);
  577.             goto loop;
  578.         }
  579.         if (c == '\n')
  580.         {
  581.             get_line();
  582.             if (line == 0)
  583.             unterminated_comment(c_lineno, c_line, c_cptr);
  584.         }
  585.         }
  586.     }
  587.     goto loop;
  588.  
  589.     default:
  590.     goto loop;
  591.     }
  592. }
  593.  
  594.  
  595. int
  596. hexval(c)
  597. int c;
  598. {
  599.     if (c >= '0' && c <= '9')
  600.     return (c - '0');
  601.     if (c >= 'A' && c <= 'F')
  602.     return (c - 'A' + 10);
  603.     if (c >= 'a' && c <= 'f')
  604.     return (c - 'a' + 10);
  605.     return (-1);
  606. }
  607.  
  608.  
  609. bucket *
  610. get_literal()
  611. {
  612.     register int c, quote;
  613.     register int i;
  614.     register int n;
  615.     register char *s;
  616.     register bucket *bp;
  617.     int s_lineno = lineno;
  618.     char *s_line = dup_line();
  619.     char *s_cptr = s_line + (cptr - line);
  620.  
  621.     quote = *cptr++;
  622.     cinc = 0;
  623.     for (;;)
  624.     {
  625.     c = *cptr++;
  626.     if (c == quote) break;
  627.     if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
  628.     if (c == '\\')
  629.     {
  630.         char *c_cptr = cptr - 1;
  631.  
  632.         c = *cptr++;
  633.         switch (c)
  634.         {
  635.         case '\n':
  636.         get_line();
  637.         if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
  638.         continue;
  639.  
  640.         case '0': case '1': case '2': case '3':
  641.         case '4': case '5': case '6': case '7':
  642.         n = c - '0';
  643.         c = *cptr;
  644.         if (IS_OCTAL(c))
  645.         {
  646.             n = (n << 3) + (c - '0');
  647.             c = *++cptr;
  648.             if (IS_OCTAL(c))
  649.             {
  650.             n = (n << 3) + (c - '0');
  651.             ++cptr;
  652.             }
  653.         }
  654.         if (n > MAXCHAR) illegal_character(c_cptr);
  655.         c = n;
  656.             break;
  657.  
  658.         case 'x':
  659.         c = *cptr++;
  660.         n = hexval(c);
  661.         if (n < 0 || n >= 16)
  662.             illegal_character(c_cptr);
  663.         for (;;)
  664.         {
  665.             c = *cptr;
  666.             i = hexval(c);
  667.             if (i < 0 || i >= 16) break;
  668.             ++cptr;
  669.             n = (n << 4) + i;
  670.             if (n > MAXCHAR) illegal_character(c_cptr);
  671.         }
  672.         c = n;
  673.         break;
  674.  
  675.         case 'a': c = 7; break;
  676.         case 'b': c = '\b'; break;
  677.         case 'f': c = '\f'; break;
  678.         case 'n': c = '\n'; break;
  679.         case 'r': c = '\r'; break;
  680.         case 't': c = '\t'; break;
  681.         case 'v': c = '\v'; break;
  682.         }
  683.     }
  684.     cachec(c);
  685.     }
  686.     FREE(s_line);
  687.  
  688.     n = cinc;
  689.     s = MALLOC(n);
  690.     if (s == 0) no_space();
  691.     
  692.     for (i = 0; i < n; ++i)
  693.     s[i] = cache[i];
  694.  
  695.     cinc = 0;
  696.     if (n == 1)
  697.     cachec('\'');
  698.     else
  699.     cachec('"');
  700.  
  701.     for (i = 0; i < n; ++i)
  702.     {
  703.     c = ((unsigned char *)s)[i];
  704.     if (c == '\\' || c == cache[0])
  705.     {
  706.         cachec('\\');
  707.         cachec(c);
  708.     }
  709.     else if (isprint(c))
  710.         cachec(c);
  711.     else
  712.     {
  713.         cachec('\\');
  714.         switch (c)
  715.         {
  716.         case 7: cachec('a'); break;
  717.         case '\b': cachec('b'); break;
  718.         case '\f': cachec('f'); break;
  719.         case '\n': cachec('n'); break;
  720.         case '\r': cachec('r'); break;
  721.         case '\t': cachec('t'); break;
  722.         case '\v': cachec('v'); break;
  723.         default:
  724.         cachec(((c >> 6) & 7) + '0');
  725.         cachec(((c >> 3) & 7) + '0');
  726.         cachec((c & 7) + '0');
  727.         break;
  728.         }
  729.     }
  730.     }
  731.  
  732.     if (n == 1)
  733.     cachec('\'');
  734.     else
  735.     cachec('"');
  736.  
  737.     cachec(NUL);
  738.     bp = lookup(cache);
  739.     bp->class = TERM;
  740.     if (n == 1 && bp->value == UNDEFINED)
  741.     bp->value = *(unsigned char *)s;
  742.     FREE(s);
  743.  
  744.     return (bp);
  745. }
  746.  
  747.  
  748. int
  749. is_reserved(name)
  750. char *name;
  751. {
  752.     char *s;
  753.  
  754.     if (strcmp(name, ".") == 0 ||
  755.         strcmp(name, "$accept") == 0 ||
  756.         strcmp(name, "$end") == 0)
  757.     return (1);
  758.  
  759.     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
  760.     {
  761.     s = name + 3;
  762.     while (isdigit(*s)) ++s;
  763.     if (*s == NUL) return (1);
  764.     }
  765.  
  766.     return (0);
  767. }
  768.  
  769.  
  770. bucket *
  771. get_name()
  772. {
  773.     register int c;
  774.  
  775.     cinc = 0;
  776.     for (c = *cptr; IS_IDENT(c); c = *++cptr)
  777.     cachec(c);
  778.     cachec(NUL);
  779.  
  780.     if (is_reserved(cache)) used_reserved(cache);
  781.  
  782.     return (lookup(cache));
  783. }
  784.  
  785.  
  786. int
  787. get_number()
  788. {
  789.     register int c;
  790.     register int n;
  791.  
  792.     n = 0;
  793.     for (c = *cptr; isdigit(c); c = *++cptr)
  794.     n = 10*n + (c - '0');
  795.  
  796.     return (n);
  797. }
  798.  
  799.  
  800. char *
  801. get_tag()
  802. {
  803.     register int c;
  804.     register int i;
  805.     register char *s;
  806.     int t_lineno = lineno;
  807.     char *t_line = dup_line();
  808.     char *t_cptr = t_line + (cptr - line);
  809.  
  810.     ++cptr;
  811.     c = nextc();
  812.     if (c == EOF) unexpected_EOF();
  813.     if (!isalpha(c) && c != '_' && c != '$')
  814.     illegal_tag(t_lineno, t_line, t_cptr);
  815.  
  816.     cinc = 0;
  817.     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
  818.     cachec(NUL);
  819.  
  820.     c = nextc();
  821.     if (c == EOF) unexpected_EOF();
  822.     if (c != '>')
  823.     illegal_tag(t_lineno, t_line, t_cptr);
  824.     ++cptr;
  825.  
  826.     for (i = 0; i < ntags; ++i)
  827.     {
  828.     if (strcmp(cache, tag_table[i]) == 0)
  829.         return (tag_table[i]);
  830.     }
  831.  
  832.     if (ntags >= tagmax)
  833.     {
  834.     tagmax += 16;
  835.     tag_table = (char **)
  836.             (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
  837.                    : MALLOC(tagmax*sizeof(char *)));
  838.     if (tag_table == 0) no_space();
  839.     }
  840.  
  841.     s = MALLOC(cinc);
  842.     if  (s == 0) no_space();
  843.     strcpy(s, cache);
  844.     tag_table[ntags] = s;
  845.     ++ntags;
  846.     FREE(t_line);
  847.     return (s);
  848. }
  849.  
  850.  
  851. declare_tokens(assoc)
  852. int assoc;
  853. {
  854.     register int c;
  855.     register bucket *bp;
  856.     int value;
  857.     char *tag = 0;
  858.  
  859.     if (assoc != TOKEN) ++prec;
  860.  
  861.     c = nextc();
  862.     if (c == EOF) unexpected_EOF();
  863.     if (c == '<')
  864.     {
  865.     tag = get_tag();
  866.     c = nextc();
  867.     if (c == EOF) unexpected_EOF();
  868.     }
  869.  
  870.     for (;;)
  871.     {
  872.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  873.         bp = get_name();
  874.     else if (c == '\'' || c == '"')
  875.         bp = get_literal();
  876.     else
  877.         return;
  878.  
  879.     if (bp == goal) tokenized_start(bp->name);
  880.     bp->class = TERM;
  881.  
  882.     if (tag)
  883.     {
  884.         if (bp->tag && tag != bp->tag)
  885.         retyped_warning(bp->name);
  886.         bp->tag = tag;
  887.     }
  888.  
  889.     if (assoc != TOKEN)
  890.     {
  891.         if (bp->prec && prec != bp->prec)
  892.         reprec_warning(bp->name);
  893.         bp->assoc = assoc;
  894.         bp->prec = prec;
  895.     }
  896.  
  897.     c = nextc();
  898.     if (c == EOF) unexpected_EOF();
  899.     value = UNDEFINED;
  900.     if (isdigit(c))
  901.     {
  902.         value = get_number();
  903.         if (bp->value != UNDEFINED && value != bp->value)
  904.         revalued_warning(bp->name);
  905.         bp->value = value;
  906.         c = nextc();
  907.         if (c == EOF) unexpected_EOF();
  908.     }
  909.     }
  910. }
  911.  
  912.  
  913. declare_types()
  914. {
  915.     register int c;
  916.     register bucket *bp;
  917.     char *tag;
  918.  
  919.     c = nextc();
  920.     if (c == EOF) unexpected_EOF();
  921.     if (c != '<') syntax_error(lineno, line, cptr);
  922.     tag = get_tag();
  923.  
  924.     for (;;)
  925.     {
  926.     c = nextc();
  927.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  928.         bp = get_name();
  929.     else if (c == '\'' || c == '"')
  930.         bp = get_literal();
  931.     else
  932.         return;
  933.  
  934.     if (bp->tag && tag != bp->tag)
  935.         retyped_warning(bp->name);
  936.     bp->tag = tag;
  937.     }
  938. }
  939.  
  940.  
  941. declare_start()
  942. {
  943.     register int c;
  944.     register bucket *bp;
  945.  
  946.     c = nextc();
  947.     if (c == EOF) unexpected_EOF();
  948.     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
  949.     syntax_error(lineno, line, cptr);
  950.     bp = get_name();
  951.     if (bp->class == TERM)
  952.     terminal_start(bp->name);
  953.     if (goal && goal != bp)
  954.     restarted_warning();
  955.     goal = bp;
  956. }
  957.  
  958.  
  959. read_declarations()
  960. {
  961.     register int c, k;
  962.  
  963.     cache_size = 256;
  964.     cache = MALLOC(cache_size);
  965.     if (cache == 0) no_space();
  966.  
  967.     for (;;)
  968.     {
  969.     c = nextc();
  970.     if (c == EOF) unexpected_EOF();
  971.     if (c != '%') syntax_error(lineno, line, cptr);
  972.     switch (k = keyword())
  973.     {
  974.     case MARK:
  975.         return;
  976.  
  977.     case IDENT:
  978.         copy_ident();
  979.         break;
  980.  
  981.     case TEXT:
  982.         copy_text();
  983.         break;
  984.  
  985.     case UNION:
  986.         copy_union();
  987.         break;
  988.  
  989.     case TOKEN:
  990.     case LEFT:
  991.     case RIGHT:
  992.     case NONASSOC:
  993.         declare_tokens(k);
  994.         break;
  995.  
  996.     case TYPE:
  997.         declare_types();
  998.         break;
  999.  
  1000.     case START:
  1001.         declare_start();
  1002.         break;
  1003.     }
  1004.     }
  1005. }
  1006.  
  1007.  
  1008. initialize_grammar()
  1009. {
  1010.     nitems = 4;
  1011.     maxitems = 300;
  1012.     pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
  1013.     if (pitem == 0) no_space();
  1014.     pitem[0] = 0;
  1015.     pitem[1] = 0;
  1016.     pitem[2] = 0;
  1017.     pitem[3] = 0;
  1018.  
  1019.     nrules = 3;
  1020.     maxrules = 100;
  1021.     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
  1022.     if (plhs == 0) no_space();
  1023.     plhs[0] = 0;
  1024.     plhs[1] = 0;
  1025.     plhs[2] = 0;
  1026.     rprec = (short *) MALLOC(maxrules*sizeof(short));
  1027.     if (rprec == 0) no_space();
  1028.     rprec[0] = 0;
  1029.     rprec[1] = 0;
  1030.     rprec[2] = 0;
  1031.     rassoc = (char *) MALLOC(maxrules*sizeof(char));
  1032.     if (rassoc == 0) no_space();
  1033.     rassoc[0] = TOKEN;
  1034.     rassoc[1] = TOKEN;
  1035.     rassoc[2] = TOKEN;
  1036. }
  1037.  
  1038.  
  1039. expand_items()
  1040. {
  1041.     maxitems += 300;
  1042.     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
  1043.     if (pitem == 0) no_space();
  1044. }
  1045.  
  1046.  
  1047. expand_rules()
  1048. {
  1049.     maxrules += 100;
  1050.     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
  1051.     if (plhs == 0) no_space();
  1052.     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
  1053.     if (rprec == 0) no_space();
  1054.     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
  1055.     if (rassoc == 0) no_space();
  1056. }
  1057.  
  1058.  
  1059. advance_to_start()
  1060. {
  1061.     register int c;
  1062.     register bucket *bp;
  1063.     char *s_cptr;
  1064.     int s_lineno;
  1065.  
  1066.     for (;;)
  1067.     {
  1068.     c = nextc();
  1069.     if (c != '%') break;
  1070.     s_cptr = cptr;
  1071.     switch (keyword())
  1072.     {
  1073.     case MARK:
  1074.         no_grammar();
  1075.  
  1076.     case TEXT:
  1077.         copy_text();
  1078.         break;
  1079.  
  1080.     case START:
  1081.         declare_start();
  1082.         break;
  1083.  
  1084.     default:
  1085.         syntax_error(lineno, line, s_cptr);
  1086.     }
  1087.     }
  1088.  
  1089.     c = nextc();
  1090.     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
  1091.     syntax_error(lineno, line, cptr);
  1092.     bp = get_name();
  1093.     if (goal == 0)
  1094.     {
  1095.     if (bp->class == TERM)
  1096.         terminal_start(bp->name);
  1097.     goal = bp;
  1098.     }
  1099.  
  1100.     s_lineno = lineno;
  1101.     c = nextc();
  1102.     if (c == EOF) unexpected_EOF();
  1103.     if (c != ':') syntax_error(lineno, line, cptr);
  1104.     start_rule(bp, s_lineno);
  1105.     ++cptr;
  1106. }
  1107.  
  1108.  
  1109. start_rule(bp, s_lineno)
  1110. register bucket *bp;
  1111. int s_lineno;
  1112. {
  1113.     if (bp->class == TERM)
  1114.     terminal_lhs(s_lineno);
  1115.     bp->class = NONTERM;
  1116.     if (nrules >= maxrules)
  1117.     expand_rules();
  1118.     plhs[nrules] = bp;
  1119.     rprec[nrules] = UNDEFINED;
  1120.     rassoc[nrules] = TOKEN;
  1121. }
  1122.  
  1123.  
  1124. end_rule()
  1125. {
  1126.     register int i;
  1127.  
  1128.     if (!last_was_action && plhs[nrules]->tag)
  1129.     {
  1130.     for (i = nitems - 1; pitem[i]; --i) continue;
  1131.     if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
  1132.         default_action_warning();
  1133.     }
  1134.  
  1135.     last_was_action = 0;
  1136.     if (nitems >= maxitems) expand_items();
  1137.     pitem[nitems] = 0;
  1138.     ++nitems;
  1139.     ++nrules;
  1140. }
  1141.  
  1142.  
  1143. insert_empty_rule()
  1144. {
  1145.     register bucket *bp, **bpp;
  1146.  
  1147.     assert(cache);
  1148.     sprintf(cache, "$$%d", ++gensym);
  1149.     bp = make_bucket(cache);
  1150.     last_symbol->next = bp;
  1151.     last_symbol = bp;
  1152.     bp->tag = plhs[nrules]->tag;
  1153.     bp->class = NONTERM;
  1154.  
  1155.     if ((nitems += 2) > maxitems)
  1156.     expand_items();
  1157.     bpp = pitem + nitems - 1;
  1158.     *bpp-- = bp;
  1159.     while (bpp[0] = bpp[-1]) --bpp;
  1160.  
  1161.     if (++nrules >= maxrules)
  1162.     expand_rules();
  1163.     plhs[nrules] = plhs[nrules-1];
  1164.     plhs[nrules-1] = bp;
  1165.     rprec[nrules] = rprec[nrules-1];
  1166.     rprec[nrules-1] = 0;
  1167.     rassoc[nrules] = rassoc[nrules-1];
  1168.     rassoc[nrules-1] = TOKEN;
  1169. }
  1170.  
  1171.  
  1172. add_symbol()
  1173. {
  1174.     register int c;
  1175.     register bucket *bp;
  1176.     int s_lineno = lineno;
  1177.  
  1178.     c = *cptr;
  1179.     if (c == '\'' || c == '"')
  1180.     bp = get_literal();
  1181.     else
  1182.     bp = get_name();
  1183.  
  1184.     c = nextc();
  1185.     if (c == ':')
  1186.     {
  1187.     end_rule();
  1188.     start_rule(bp, s_lineno);
  1189.     ++cptr;
  1190.     return;
  1191.     }
  1192.  
  1193.     if (last_was_action)
  1194.     insert_empty_rule();
  1195.     last_was_action = 0;
  1196.  
  1197.     if (++nitems > maxitems)
  1198.     expand_items();
  1199.     pitem[nitems-1] = bp;
  1200. }
  1201.  
  1202.  
  1203. copy_action()
  1204. {
  1205.     register int c;
  1206.     register int i, n;
  1207.     int depth;
  1208.     int quote;
  1209.     char *tag;
  1210.     register FILE *f = action_file;
  1211.     int a_lineno = lineno;
  1212.     char *a_line = dup_line();
  1213.     char *a_cptr = a_line + (cptr - line);
  1214.  
  1215.     if (last_was_action)
  1216.     insert_empty_rule();
  1217.     last_was_action = 1;
  1218.  
  1219.     fprintf(f, "case %d:\n", nrules - 2);
  1220.     if (!lflag)
  1221.     fprintf(f, line_format, lineno, input_file_name);
  1222.     if (*cptr == '=') ++cptr;
  1223.  
  1224.     n = 0;
  1225.     for (i = nitems - 1; pitem[i]; --i) ++n;
  1226.  
  1227.     depth = 0;
  1228. loop:
  1229.     c = *cptr;
  1230.     if (c == '$')
  1231.     {
  1232.     if (cptr[1] == '<')
  1233.     {
  1234.         int d_lineno = lineno;
  1235.         char *d_line = dup_line();
  1236.         char *d_cptr = d_line + (cptr - line);
  1237.  
  1238.         ++cptr;
  1239.         tag = get_tag();
  1240.         c = *cptr;
  1241.         if (c == '$')
  1242.         {
  1243.         fprintf(f, "yyval.%s", tag);
  1244.         ++cptr;
  1245.         FREE(d_line);
  1246.         goto loop;
  1247.         }
  1248.         else if (isdigit(c))
  1249.         {
  1250.         i = get_number();
  1251.         if (i > n) dollar_warning(d_lineno, i);
  1252.         fprintf(f, "yyvsp[%d].%s", i - n, tag);
  1253.         FREE(d_line);
  1254.         goto loop;
  1255.         }
  1256.         else if (c == '-' && isdigit(cptr[1]))
  1257.         {
  1258.         ++cptr;
  1259.         i = -get_number() - n;
  1260.         fprintf(f, "yyvsp[%d].%s", i, tag);
  1261.         FREE(d_line);
  1262.         goto loop;
  1263.         }
  1264.         else
  1265.         dollar_error(d_lineno, d_line, d_cptr);
  1266.     }
  1267.     else if (cptr[1] == '$')
  1268.     {
  1269.         if (ntags)
  1270.         {
  1271.         tag = plhs[nrules]->tag;
  1272.         if (tag == 0) untyped_lhs();
  1273.         fprintf(f, "yyval.%s", tag);
  1274.         }
  1275.         else
  1276.         fprintf(f, "yyval");
  1277.         cptr += 2;
  1278.         goto loop;
  1279.     }
  1280.     else if (isdigit(cptr[1]))
  1281.     {
  1282.         ++cptr;
  1283.         i = get_number();
  1284.         if (ntags)
  1285.         {
  1286.         if (i <= 0 || i > n)
  1287.             unknown_rhs(i);
  1288.         tag = pitem[nitems + i - n - 1]->tag;
  1289.         if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
  1290.         fprintf(f, "yyvsp[%d].%s", i - n, tag);
  1291.         }
  1292.         else
  1293.         {
  1294.         if (i > n)
  1295.             dollar_warning(lineno, i);
  1296.         fprintf(f, "yyvsp[%d]", i - n);
  1297.         }
  1298.         goto loop;
  1299.     }
  1300.     else if (cptr[1] == '-')
  1301.     {
  1302.         cptr += 2;
  1303.         i = get_number();
  1304.         if (ntags)
  1305.         unknown_rhs(-i);
  1306.         fprintf(f, "yyvsp[%d]", -i - n);
  1307.         goto loop;
  1308.     }
  1309.     }
  1310.     if (isalpha(c) || c == '_' || c == '$')
  1311.     {
  1312.     do
  1313.     {
  1314.         putc(c, f);
  1315.         c = *++cptr;
  1316.     } while (isalnum(c) || c == '_' || c == '$');
  1317.     goto loop;
  1318.     }
  1319.     putc(c, f);
  1320.     ++cptr;
  1321.     switch (c)
  1322.     {
  1323.     case '\n':
  1324.     next_line:
  1325.     get_line();
  1326.     if (line) goto loop;
  1327.     unterminated_action(a_lineno, a_line, a_cptr);
  1328.  
  1329.     case ';':
  1330.     if (depth > 0) goto loop;
  1331.     fprintf(f, "\nbreak;\n");
  1332.     return;
  1333.  
  1334.     case '{':
  1335.     ++depth;
  1336.     goto loop;
  1337.  
  1338.     case '}':
  1339.     if (--depth > 0) goto loop;
  1340.     fprintf(f, "\nbreak;\n");
  1341.     return;
  1342.  
  1343.     case '\'':
  1344.     case '"':
  1345.     {
  1346.         int s_lineno = lineno;
  1347.         char *s_line = dup_line();
  1348.         char *s_cptr = s_line + (cptr - line - 1);
  1349.  
  1350.         quote = c;
  1351.         for (;;)
  1352.         {
  1353.         c = *cptr++;
  1354.         putc(c, f);
  1355.         if (c == quote)
  1356.         {
  1357.             FREE(s_line);
  1358.             goto loop;
  1359.         }
  1360.         if (c == '\n')
  1361.             unterminated_string(s_lineno, s_line, s_cptr);
  1362.         if (c == '\\')
  1363.         {
  1364.             c = *cptr++;
  1365.             putc(c, f);
  1366.             if (c == '\n')
  1367.             {
  1368.             get_line();
  1369.             if (line == 0)
  1370.                 unterminated_string(s_lineno, s_line, s_cptr);
  1371.             }
  1372.         }
  1373.         }
  1374.     }
  1375.  
  1376.     case '/':
  1377.     c = *cptr;
  1378.     if (c == '/')
  1379.     {
  1380.         putc('*', f);
  1381.         while ((c = *++cptr) != '\n')
  1382.         {
  1383.         if (c == '*' && cptr[1] == '/')
  1384.             fprintf(f, "* ");
  1385.         else
  1386.             putc(c, f);
  1387.         }
  1388.         fprintf(f, "*/\n");
  1389.         goto next_line;
  1390.     }
  1391.     if (c == '*')
  1392.     {
  1393.         int c_lineno = lineno;
  1394.         char *c_line = dup_line();
  1395.         char *c_cptr = c_line + (cptr - line - 1);
  1396.  
  1397.         putc('*', f);
  1398.         ++cptr;
  1399.         for (;;)
  1400.         {
  1401.         c = *cptr++;
  1402.         putc(c, f);
  1403.         if (c == '*' && *cptr == '/')
  1404.         {
  1405.             putc('/', f);
  1406.             ++cptr;
  1407.             FREE(c_line);
  1408.             goto loop;
  1409.         }
  1410.         if (c == '\n')
  1411.         {
  1412.             get_line();
  1413.             if (line == 0)
  1414.             unterminated_comment(c_lineno, c_line, c_cptr);
  1415.         }
  1416.         }
  1417.     }
  1418.     goto loop;
  1419.  
  1420.     default:
  1421.     goto loop;
  1422.     }
  1423. }
  1424.  
  1425.  
  1426. int
  1427. mark_symbol()
  1428. {
  1429.     register int c;
  1430.     register bucket *bp;
  1431.  
  1432.     c = cptr[1];
  1433.     if (c == '%' || c == '\\')
  1434.     {
  1435.     cptr += 2;
  1436.     return (1);
  1437.     }
  1438.  
  1439.     if (c == '=')
  1440.     cptr += 2;
  1441.     else if ((c == 'p' || c == 'P') &&
  1442.          ((c = cptr[2]) == 'r' || c == 'R') &&
  1443.          ((c = cptr[3]) == 'e' || c == 'E') &&
  1444.          ((c = cptr[4]) == 'c' || c == 'C') &&
  1445.          ((c = cptr[5], !IS_IDENT(c))))
  1446.     cptr += 5;
  1447.     else
  1448.     syntax_error(lineno, line, cptr);
  1449.  
  1450.     c = nextc();
  1451.     if (isalpha(c) || c == '_' || c == '.' || c == '$')
  1452.     bp = get_name();
  1453.     else if (c == '\'' || c == '"')
  1454.     bp = get_literal();
  1455.     else
  1456.     {
  1457.     syntax_error(lineno, line, cptr);
  1458.     /*NOTREACHED*/
  1459.     }
  1460.  
  1461.     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
  1462.     prec_redeclared();
  1463.  
  1464.     rprec[nrules] = bp->prec;
  1465.     rassoc[nrules] = bp->assoc;
  1466.     return (0);
  1467. }
  1468.  
  1469.  
  1470. read_grammar()
  1471. {
  1472.     register int c;
  1473.  
  1474.     initialize_grammar();
  1475.     advance_to_start();
  1476.  
  1477.     for (;;)
  1478.     {
  1479.     c = nextc();
  1480.     if (c == EOF) break;
  1481.     if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
  1482.         c == '"')
  1483.         add_symbol();
  1484.     else if (c == '{' || c == '=')
  1485.         copy_action();
  1486.     else if (c == '|')
  1487.     {
  1488.         end_rule();
  1489.         start_rule(plhs[nrules-1], 0);
  1490.         ++cptr;
  1491.     }
  1492.     else if (c == '%')
  1493.     {
  1494.         if (mark_symbol()) break;
  1495.     }
  1496.     else
  1497.         syntax_error(lineno, line, cptr);
  1498.     }
  1499.     end_rule();
  1500. }
  1501.  
  1502.  
  1503. free_tags()
  1504. {
  1505.     register int i;
  1506.  
  1507.     if (tag_table == 0) return;
  1508.  
  1509.     for (i = 0; i < ntags; ++i)
  1510.     {
  1511.     assert(tag_table[i]);
  1512.     FREE(tag_table[i]);
  1513.     }
  1514.     FREE(tag_table);
  1515. }
  1516.  
  1517.  
  1518. pack_names()
  1519. {
  1520.     register bucket *bp;
  1521.     register char *p, *s, *t;
  1522.  
  1523.     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
  1524.     for (bp = first_symbol; bp; bp = bp->next)
  1525.     name_pool_size += strlen(bp->name) + 1;
  1526.     name_pool = MALLOC(name_pool_size);
  1527.     if (name_pool == 0) no_space();
  1528.  
  1529.     strcpy(name_pool, "$accept");
  1530.     strcpy(name_pool+8, "$end");
  1531.     t = name_pool + 13;
  1532.     for (bp = first_symbol; bp; bp = bp->next)
  1533.     {
  1534.     p = t;
  1535.     s = bp->name;
  1536.     while (*t++ = *s++) continue;
  1537.     FREE(bp->name);
  1538.     bp->name = p;
  1539.     }
  1540. }
  1541.  
  1542.  
  1543. check_symbols()
  1544. {
  1545.     register bucket *bp;
  1546.  
  1547.     if (goal->class == UNKNOWN)
  1548.     undefined_goal(goal->name);
  1549.  
  1550.     for (bp = first_symbol; bp; bp = bp->next)
  1551.     {
  1552.     if (bp->class == UNKNOWN)
  1553.     {
  1554.         undefined_symbol_warning(bp->name);
  1555.         bp->class = TERM;
  1556.     }
  1557.     }
  1558. }
  1559.  
  1560.  
  1561. pack_symbols()
  1562. {
  1563.     register bucket *bp;
  1564.     register bucket **v;
  1565.     register int i, j, k, n;
  1566.  
  1567.     nsyms = 2;
  1568.     ntokens = 1;
  1569.     for (bp = first_symbol; bp; bp = bp->next)
  1570.     {
  1571.     ++nsyms;
  1572.     if (bp->class == TERM) ++ntokens;
  1573.     }
  1574.     start_symbol = ntokens;
  1575.     nvars = nsyms - ntokens;
  1576.  
  1577.     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
  1578.     if (symbol_name == 0) no_space();
  1579.     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
  1580.     if (symbol_value == 0) no_space();
  1581.     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
  1582.     if (symbol_prec == 0) no_space();
  1583.     symbol_assoc = MALLOC(nsyms);
  1584.     if (symbol_assoc == 0) no_space();
  1585.  
  1586.     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
  1587.     if (v == 0) no_space();
  1588.  
  1589.     v[0] = 0;
  1590.     v[start_symbol] = 0;
  1591.  
  1592.     i = 1;
  1593.     j = start_symbol + 1;
  1594.     for (bp = first_symbol; bp; bp = bp->next)
  1595.     {
  1596.     if (bp->class == TERM)
  1597.         v[i++] = bp;
  1598.     else
  1599.         v[j++] = bp;
  1600.     }
  1601.     assert(i == ntokens && j == nsyms);
  1602.  
  1603.     for (i = 1; i < ntokens; ++i)
  1604.     v[i]->index = i;
  1605.  
  1606.     goal->index = start_symbol + 1;
  1607.     k = start_symbol + 2;
  1608.     while (++i < nsyms)
  1609.     if (v[i] != goal)
  1610.     {
  1611.         v[i]->index = k;
  1612.         ++k;
  1613.     }
  1614.  
  1615.     goal->value = 0;
  1616.     k = 1;
  1617.     for (i = start_symbol + 1; i < nsyms; ++i)
  1618.     {
  1619.     if (v[i] != goal)
  1620.     {
  1621.         v[i]->value = k;
  1622.         ++k;
  1623.     }
  1624.     }
  1625.  
  1626.     k = 0;
  1627.     for (i = 1; i < ntokens; ++i)
  1628.     {
  1629.     n = v[i]->value;
  1630.     if (n > 256)
  1631.     {
  1632.         for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
  1633.         symbol_value[j] = symbol_value[j-1];
  1634.         symbol_value[j] = n;
  1635.     }
  1636.     }
  1637.  
  1638.     if (v[1]->value == UNDEFINED)
  1639.     v[1]->value = 256;
  1640.  
  1641.     j = 0;
  1642.     n = 257;
  1643.     for (i = 2; i < ntokens; ++i)
  1644.     {
  1645.     if (v[i]->value == UNDEFINED)
  1646.     {
  1647.         while (j < k && n == symbol_value[j])
  1648.         {
  1649.         while (++j < k && n == symbol_value[j]) continue;
  1650.         ++n;
  1651.         }
  1652.         v[i]->value = n;
  1653.         ++n;
  1654.     }
  1655.     }
  1656.  
  1657.     symbol_name[0] = name_pool + 8;
  1658.     symbol_value[0] = 0;
  1659.     symbol_prec[0] = 0;
  1660.     symbol_assoc[0] = TOKEN;
  1661.     for (i = 1; i < ntokens; ++i)
  1662.     {
  1663.     symbol_name[i] = v[i]->name;
  1664.     symbol_value[i] = v[i]->value;
  1665.     symbol_prec[i] = v[i]->prec;
  1666.     symbol_assoc[i] = v[i]->assoc;
  1667.     }
  1668.     symbol_name[start_symbol] = name_pool;
  1669.     symbol_value[start_symbol] = -1;
  1670.     symbol_prec[start_symbol] = 0;
  1671.     symbol_assoc[start_symbol] = TOKEN;
  1672.     for (++i; i < nsyms; ++i)
  1673.     {
  1674.     k = v[i]->index;
  1675.     symbol_name[k] = v[i]->name;
  1676.     symbol_value[k] = v[i]->value;
  1677.     symbol_prec[k] = v[i]->prec;
  1678.     symbol_assoc[k] = v[i]->assoc;
  1679.     }
  1680.  
  1681.     FREE(v);
  1682. }
  1683.  
  1684.  
  1685. pack_grammar()
  1686. {
  1687.     register int i, j;
  1688.     int assoc, prec;
  1689.  
  1690.     ritem = (short *) MALLOC(nitems*sizeof(short));
  1691.     if (ritem == 0) no_space();
  1692.     rlhs = (short *) MALLOC(nrules*sizeof(short));
  1693.     if (rlhs == 0) no_space();
  1694.     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
  1695.     if (rrhs == 0) no_space();
  1696.     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
  1697.     if (rprec == 0) no_space();
  1698.     rassoc = REALLOC(rassoc, nrules);
  1699.     if (rassoc == 0) no_space();
  1700.  
  1701.     ritem[0] = -1;
  1702.     ritem[1] = goal->index;
  1703.     ritem[2] = 0;
  1704.     ritem[3] = -2;
  1705.     rlhs[0] = 0;
  1706.     rlhs[1] = 0;
  1707.     rlhs[2] = start_symbol;
  1708.     rrhs[0] = 0;
  1709.     rrhs[1] = 0;
  1710.     rrhs[2] = 1;
  1711.  
  1712.     j = 4;
  1713.     for (i = 3; i < nrules; ++i)
  1714.     {
  1715.     rlhs[i] = plhs[i]->index;
  1716.     rrhs[i] = j;
  1717.     assoc = TOKEN;
  1718.     prec = 0;
  1719.     while (pitem[j])
  1720.     {
  1721.         ritem[j] = pitem[j]->index;
  1722.         if (pitem[j]->class == TERM)
  1723.         {
  1724.         prec = pitem[j]->prec;
  1725.         assoc = pitem[j]->assoc;
  1726.         }
  1727.         ++j;
  1728.     }
  1729.     ritem[j] = -i;
  1730.     ++j;
  1731.     if (rprec[i] == UNDEFINED)
  1732.     {
  1733.         rprec[i] = prec;
  1734.         rassoc[i] = assoc;
  1735.     }
  1736.     }
  1737.     rrhs[i] = j;
  1738.  
  1739.     FREE(plhs);
  1740.     FREE(pitem);
  1741. }
  1742.  
  1743.  
  1744. print_grammar()
  1745. {
  1746.     register int i, j, k;
  1747.     int spacing;
  1748.     register FILE *f = verbose_file;
  1749.  
  1750.     if (!vflag) return;
  1751.  
  1752.     k = 1;
  1753.     for (i = 2; i < nrules; ++i)
  1754.     {
  1755.     if (rlhs[i] != rlhs[i-1])
  1756.     {
  1757.         if (i != 2) fprintf(f, "\n");
  1758.         fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
  1759.         spacing = strlen(symbol_name[rlhs[i]]) + 1;
  1760.     }
  1761.     else
  1762.     {
  1763.         fprintf(f, "%4d  ", i - 2);
  1764.         j = spacing;
  1765.         while (--j >= 0) putc(' ', f);
  1766.         putc('|', f);
  1767.     }
  1768.  
  1769.     while (ritem[k] >= 0)
  1770.     {
  1771.         fprintf(f, " %s", symbol_name[ritem[k]]);
  1772.         ++k;
  1773.     }
  1774.     ++k;
  1775.     putc('\n', f);
  1776.     }
  1777. }
  1778.  
  1779.  
  1780. reader()
  1781. {
  1782.     write_section(banner);
  1783.     create_symbol_table();
  1784.     read_declarations();
  1785.     read_grammar();
  1786.     free_symbol_table();
  1787.     free_tags();
  1788.     pack_names();
  1789.     check_symbols();
  1790.     pack_symbols();
  1791.     pack_grammar();
  1792.     free_symbols();
  1793.     print_grammar();
  1794. }
  1795. @
  1796.